﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AsyncAwait
{
    public class AsyncWaiteRun
    {
        //(lock monitor 可以设置等待时间防止死锁 阻塞锁、互斥锁,被动咨询加锁)  //单进程使用

        //（spnlock自旋锁,非阻塞锁，主动咨询加锁,适用于执行时间比较短的情况）

        //readwriterlockslim 读写锁 所有的读线程，都可以同时获取锁。 所有的写线程，只有一个线程能够获取到锁 
        //规则;读线程获取到读锁，读取完成后，写线程才能获取到写锁，写数据
        //写线程获取到写锁，修改数据完后，读线程才能获取到读锁，读数据  适用于高并发读数据的时候，写数据少的时候

        //semaphoreslim  限制线程访问  使用semaphoreslim解决多线程访问共享资源读写的问题 线程限流 高并发访问数据的情况下

        //mutex 跨进程多进程使用 解决多进程访问共享资源的问题 只能在同一个操作系统上，实现进程锁x

        //阻塞锁 ：一个线程执行的同时，其他线程等待
        //spinlock 自旋锁   非阻塞锁 主动咨询加锁
        public static void Run()
        {
            //互斥锁
            //Thread thread = new Thread(RunCount);
            //thread.IsBackground = false;
            //Thread thread1 = new Thread(RunCount);
            //thread1.IsBackground = false;
            //thread.Start();
            //thread1.Start();
            //thread1.Join();
            //thread.Join();
            //Console.WriteLine(Count);

            //自旋锁
            //List<Task> tasks = new List<Task>();
            //tasks.Add(Task.Run(() => { RunCountSpinLock(); }));
            //tasks.Add(Task.Run(() => { RunCountSpinLock(); }));
            //tasks.Add(Task.Run(() => { RunCountSpinLock(); }));
            //Task.WaitAll(tasks.ToArray());
            //Console.WriteLine(Count);

            //添加值
            //readwriterlockslim 读写锁
            //List<Task> tasks = new List<Task>();
            //tasks.Add(Task.Run(() => { ReadCount(); }));
            //tasks.Add(Task.Run(() => { ReadCount(); }));
            //tasks.Add(Task.Run(() => { ReadCount(); }));
            //tasks.Add(Task.Run(() => { WriteCount(); }));
            //tasks.Add(Task.Run(() => { WriteCount(); }));
            //tasks.Add(Task.Run(() => { WriteCount(); }));
            //Task.WhenAll(tasks).Wait();

            List<Task> tasks = new List<Task>();
            if (!File.Exists(filepath)) {
                File.Create(filepath);
            }
            tasks.Add(Task.Run(() => { RunMutex(); }));
            tasks.Add(Task.Run(() => { RunMutex(); }));
            Task.WhenAll(tasks).Wait();
        }

        public static int Count { get; set; }
        public static object ob = new object();

        static SpinLock spinLock = new SpinLock();

        public static ReaderWriterLockSlim ReaderWriterLockSlim = new ReaderWriterLockSlim();

        public static Mutex mutex = new Mutex(false, "globleTest");

        public static string filepath = "E:\\项目\\镜像仓库\\twotestapp\\oneapi\\AsyncAwait\\textxx.txt";

        public static void RunMutex()
        {
            for (int i = 0; i < 7; i++)
            {
                mutex.WaitOne();
                string str = File.ReadAllText(filepath);
                str += "正在写入\r\n";
                File.WriteAllText(filepath, str);
                Console.WriteLine("正在写入");
                Task.Delay(1000).Wait();
                mutex.ReleaseMutex();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void ReadCount()
        {
            for (int i = 0; i < 5; i++)
            {
                ReaderWriterLockSlim.EnterReadLock();
                Console.WriteLine(Count);
                Task.Delay(1000).Wait();
                ReaderWriterLockSlim.ExitReadLock();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void WriteCount()
        {
            for (int i = 0; i < 5; i++)
            {
                ReaderWriterLockSlim.EnterWriteLock();
                Count++;
                Console.WriteLine("添加值");
                Task.Delay(1000).Wait();
                ReaderWriterLockSlim.ExitWriteLock();
            }
        }

        public static void RunCount()
        {
            for (int i = 0; i < 5; i++)
            {
                var xx = Monitor.TryEnter(ob, 1000);
                if (xx)
                {
                    Count++;
                    Console.WriteLine("xxx");
                    Task.Delay(1500).Wait();
                    Monitor.Exit(ob);
                }
                else
                {
                    Console.WriteLine("等待超时");
                }
            }
        }

        /// <summary>
        ///  
        /// </summary>
        public static void RunCountSpinLock()
        {

            for (int i = 0; i < 5; i++)
            {
                bool bl = false;
                //var xx = Monitor.TryEnter(ob, 1000);
                spinLock.TryEnter(1000, ref bl);
                try
                {
                    Count++;
                    Console.WriteLine("xxx");
                    Task.Delay(3000).Wait();
                    //Monitor.Exit(ob);
                }
                finally
                {

                }
                if (bl)
                {
                    spinLock.Exit();
                }
            }
        }
    }
}
